package com.csmall.stock.webapi.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.csmall.commons.pojo.stock.dto.StockReduceCountDTO;
import com.csmall.commons.restful.JsonResult;
import com.csmall.commons.restful.ResponseCode;
import com.csmall.stock.service.StockService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Name: StockController
 * @Author: 西风残叶
 * @Date: 2024/8/18 19:14
 * @Version: 1.0
 * @TODO: TODO
 */
@RestController
@RequestMapping("/base/stock")
@Api(tags = "库存服务")
@Slf4j
public class StockController {
    @Autowired
    private StockService stockService;

    /**
     * @param stockReduceCountDTO :接收到的参数
     * @return :JsonResult
     * fallback:处理降级的方法
     * blockHandler:处理限流操作失败的异常情况
     */
    @PostMapping("/reduce/count")
    @ApiOperation("减少库存")
    @SentinelResource(value = "减少库存数",
            blockHandler = "blockError",
            fallback = "fallbackError")
    public JsonResult reduceStockCount(StockReduceCountDTO stockReduceCountDTO) {
        stockService.reduceStockCount(stockReduceCountDTO);
        return JsonResult.ok("库存减少成功");
    }

    /**
     * 处理库存减少操作失败的异常情况
     * 该方法主要用于在库存减少操作失败时，返回一个包含错误信息的Json结果
     *
     * @param stockReduceCountDTO 库存减少的请求数据传输对象，包含了操作所需的信息
     * @param e                   BlockException异常对象，表示库存减少操作失败的具体异常
     * @return JsonResult 返回一个表示操作失败的Json结果，包含错误代码和错误信息
     * 方法命名必须与被注解的方法名相同，且返回类型必须与被注解的方法的返回类型相同
     * 方法必须和控制器一致，并且方法参数必须和注解方法参数一致,并且额外添加一个BlockException参数表示限流异常
     * <p>
     * 注释解释：为什么需要这个方法？因为在库存减少操作中可能会遇到各种问题（如库存不足、数据错误等），
     * 该方法通过记录错误日志并返回一个标准的错误Json结果，使得调用方能够快速获知操作失败的原因并作出相应处理。
     */
    public JsonResult blockError(StockReduceCountDTO stockReduceCountDTO, BlockException e) {
        return JsonResult.failed(ResponseCode.INTERNAL_SERVER_ERROR, "服务器忙,请稍后重试!");
    }

    /**
     * 自定义降级方法
     * @param stockReduceCountDTO :参数
     * @param e :异常
     * @return :JsonResult
     */
    public JsonResult fallbackError(StockReduceCountDTO stockReduceCountDTO, Throwable e) {
        e.printStackTrace();
        return JsonResult.failed(ResponseCode.INTERNAL_SERVER_ERROR, "服务器忙,请稍后重试!");
    }
}